package com.blog.common;


import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import org.apache.log4j.Logger;

import java.lang.management.*;
import java.util.List;

public class MonitorServlet extends HttpServlet {
    private static Logger logger = Logger.getLogger(MonitorServlet.class);
    /**
	 * Initialization of the servlet. <br>
	 *
	 * @throws javax.servlet.ServletException if an error occurs
	 */
	public void init() throws ServletException {
        new Thread(new Runnable() {
            @Override
            public void run() {
                long interval_time = Long.parseLong(getInitParameter("interval_time"))*1000;
                while(true){
                    StringBuilder sb = new StringBuilder();
                    sb.append(printMemoryMXBean()).append(" ");
                    sb.append(printThreadMXBean()).append(" ");
                    sb.append(printGarbageCollectorMXBean());
                    logger.error(sb.toString());
                    try {
                        Thread.sleep(interval_time);
                    } catch (InterruptedException e) {
                        logger.error("",e);
                    }
                }
            }
        }).start();
	}



    //内存，最大，最小，当前已分配
    private static String printMemoryMXBean() {
        StringBuilder sb = new StringBuilder();
        // 获得单一实例
        MemoryMXBean instance = ManagementFactory.getMemoryMXBean();
        // 返回用于对象分配的堆的当前内存使用量
        sb.append("heap_memory_usage:").append(printMemoryUsageInfo(instance.getHeapMemoryUsage()));
        // 返回Java虚拟机使用的非堆内存的当前使用量
        sb.append(" non_heap_memory_usage:").append(printMemoryUsageInfo(instance.getNonHeapMemoryUsage()));
        return sb.toString();
    }

    //线程数目，状态，汇总
    private static String printThreadMXBean() {
        StringBuilder sb = new StringBuilder();
        // 获得单一实例
        ThreadMXBean instance = ManagementFactory.getThreadMXBean();
        // 返回活动线程ID
        ThreadInfo[] threadInfos = instance.getThreadInfo(instance.getAllThreadIds());
        int resinCount=0;
        int runnableCount=0;
        int blockedCount=0;
        int waitingCount=0;
        for(ThreadInfo threadInfo : threadInfos) {
            String name = threadInfo.getThreadName();
            Thread.State state = threadInfo.getThreadState();
            if(name.contains("tomcat")){
                resinCount++;
                if(state.equals(Thread.State.RUNNABLE)) {
                    runnableCount++;
                } else if(state.equals(Thread.State.BLOCKED)){
                    blockedCount++;
                } else if(state.equals(Thread.State.WAITING)||state.equals(Thread.State.TIMED_WAITING)){
                    waitingCount++;
                }
            }
        }
        sb.append("thread:");
        sb.append("resin_count=").append(resinCount);
        sb.append(",runnable_count=").append(runnableCount);
        sb.append(",block_count=").append(blockedCount);
        sb.append(",waiting_count=").append(waitingCount);
        return sb.toString();
    }

    //垃圾回收 次数 执行时间
    private static String printGarbageCollectorMXBean() {
        StringBuilder sb = new StringBuilder();
        // 获得单一实例
        List<GarbageCollectorMXBean> instances = ManagementFactory
                .getGarbageCollectorMXBeans();
        // 遍历每个实例
        for (GarbageCollectorMXBean instance : instances) {
            // 返回垃圾收集器的名字

            sb.append("GC_").append(instance.getName().replaceAll(" ","-")).append(":");
            // 返回已发生的回收的总次数
            sb.append("colletion_count=").append(instance.getCollectionCount());
            // 返回近似的累积回收时间
            sb.append(",collection_time=").append(instance.getCollectionTime()).append(" ");
        }
        return sb.toString();
    }

    /**
     * Returns a descriptive representation of this memory usage.
     */
    private static String printMemoryUsageInfo(MemoryUsage usage) {
        StringBuilder buf = new StringBuilder();
        buf.append("init=").append(usage.getInit() >> 20).append("M,");
        buf.append("used=").append(usage.getUsed() >> 20).append("M,");
        buf.append("committed=").append(usage.getCommitted() >> 20).append("M,");
        buf.append("max=").append(usage.getMax() >> 20).append("M");
        return buf.toString();
    }
}
